from os import *
from sys import *
from tkinter.filedialog import *
from tkinter import *
from tkinter.ttk import *
from shutil import *

system_str, py_file_path, get_path, spec, out_path, file_name, work_path = \
    "", "", "", "", "", "", ""

# 检查pyinstaller是否安装
system(f"{executable} -m pip install pyinstaller ")


def get_path_():  # 获取文件路径
    try:
        global py_file_path, get_path, spec, out_path, file_name, work_path  # 全局变量

        # 获取文件路径
        py_file_path = askopenfilename(title='选择一个文件进行编译', filetypes=[('python文件', '.py'), ('python文件', '.pyw')], )

        # 获取输出路径
        out_path = askdirectory(title='选择一个输出路径')

        # 获取当前工作路径
        spec_path = getcwdb().decode()

        # 提取文件的目录
        get_path = "/".join(py_file_path.split("/")[:-1])

        # 提示
        print("当前输出目录:", out_path)
        print("当前文件路径:", py_file_path)
        print("当前文件目录:", get_path)

        # cd 到py文件目录
        system(get_path[0] + ":")
        system("CD " + get_path)

        # 提取文件名
        file_name = "".join("".join(py_file_path.split("/")[-1:]).split(".")[:-1])

        # 获取spec文件名
        spec = file_name + ".spec"
        # 取消提示
        Style.configure("get_path.TButton", text="请选择你的编译方式", foreground="#000000")
    except IndexError:
        pass


def have_get_path() -> bool:
    global file_name, get_path
    try:
        chdir(get_path)
        if "build" in listdir():
            chdir("build")
            if file_name in listdir():
                return True
        return False
    except OSError:
        return False


def have_out_path() -> bool:
    global file_name, out_path
    try:
        # os 工作目录 到 输出目录
        chdir(out_path)
        # 处理 输出目录有相同文件或目录
        # 如果 构建目录 在 输出目录 中
        if "build" in listdir():
            # os 工作目录 到 构建目录
            chdir("build")
            # 如果 单个文件构建目录 在 构建目录 中
            if file_name in listdir():
                return True
        return False
    except OSError:
        return False


# 移动文件函数
def move_file():
    # -移动build-
    if have_get_path():
        if have_out_path():
            # os 删除 spec文件
            remove(f"{out_path}/{spec}")
            rmtree(f"{out_path}/build/{file_name}/")
        # st 移动 spec文件 到 输出目录
        move(f"{work_path}/{spec}", out_path)
        # 移动 单个文件构建目录 到 输出目录中的构建目录中
        move(f"{work_path}/build/{file_name}", f"{out_path}/build/{file_name}/")
        # rmtree(f"{get_path}/build/")
        # 提示
        print("已移动构建目录")
        print("已移动spec文件")


# 定义 函数:编译
def run():
    # 提示
    progressbarOne.start()
    progressbarOne.pack()
    out_TLabel.configure(text="正在编译...", foreground="red")
    win.update()
    # cmd 工作目录 到 输出目录
    system(f"CD {get_path}")
    # cmd 执行编译命令
    system(system_str)
    if have_get_path() or have_out_path():
        # 调用 移动文件函数
        move_file()
        # 如果 多选按钮:删除构建文件 被勾选
        if check_del.get() == 1:
            # 调用 删除构建文件 函数
            del_file()
        # cmd 弹出 输出目录:文件管理器窗口
        system(f"START {out_path}")
        # 提示
        progressbarOne.pack_forget()
        out_TLabel.configure(text="编译完成", foreground="#32e249")
        get_path_TButton.configure(text="选择文件与输出目录")
        Style.configure("get_path.TButton", foreground="#000000")
    else:
        progressbarOne.pack_forget()
        Style.configure("get_path.TButton", foreground="red")
        get_path_TButton.configure(text="请先选择选择文件与输出目录")
        out_TLabel.configure(text="")


# 定义 函数:删除构建文件
def del_file():
    # os 删除 spec文件
    remove(f"{get_path}/{spec}")
    # cmd 删除 构建目录文件
    rmtree(f"{out_path}/build/{file_name}/")


# pyinstaller -F -w  F:\Py_file\CYH-Py_file\Py_file_pycharm\测试.py  ––workpath build ––distpath
# F:\Py_file\CYH-Py_file\pyinstaller_file\

# 定义 按钮1:产生单个的可执行文件 触发事件
def command_1():
    # 全局变量
    global system_str
    # 如果 多选按钮:命令行程序 被勾选
    if not check_var.get() == 1:
        # 赋值 编译代码 单文件 命令行窗口
        system_str = f"pyinstaller -F  {py_file_path} --workpath {out_path}/build --distpath {out_path}/"
    # 如果 多选按钮:命令行程序 没有被勾选
    else:
        # 赋值 编译代码 单文件 无命令行窗口
        system_str = f"pyinstaller -F -w {py_file_path} --workpath {out_path}/build --distpath {out_path}/"
    # 调用 编译 函数
    run()


# 定义 按钮2:产生一个目录作为可执行程序 触发事件
def command_2():
    # 全局变量
    global system_str
    # 如果 多选按钮:删除构建文件 被勾选
    if not check_var.get():
        # 赋值 编译代码 : 目录构建 命令行窗口
        system_str = f"pyinstaller  {py_file_path} --workpath {out_path}/build --distpath {out_path}/"
    # 如果 多选按钮:删除构建文件 没有被勾选
    else:
        # 赋值 编译代码 : 目录构建 无命令行窗口
        system_str = f"pyinstaller -w {py_file_path} --workpath {out_path}/build --distpath {out_path}/"
    # 调用 编译 函数
    run()


win = Tk()
Style = Style()
win.geometry('300x200')
win.resizable(False, False)
win.title("Pyinstaller GUI")
Label(win, text="请选择你的编译方式").pack()
check_var = IntVar(master=win)
check_del = IntVar(master=win)
checkbutton1 = Checkbutton(win, text="构建GUI程序", variable=check_var)
checkbutton1.pack(side=TOP)
checkbutton2 = Checkbutton(win, text="删除构建文件", variable=check_del)
checkbutton2.pack(side=TOP)
Button(win, text="产生单个可执行程序", command=command_1).pack(side=TOP, ipadx=55)
Button(win, text="产生目录可执行程序", command=command_2).pack(side=TOP, ipadx=55)

out_TLabel = Label(win, text="", style="out.TLabel")
out_TLabel.pack(side=TOP)
progressbarOne = Progressbar(win, length=200, mode='indeterminate', orient=HORIZONTAL)
get_path_TButton = Button(win, text="选择文件与输出目录", command=get_path_, style="get_path.TButton")
Style.configure("get_path.TButton",foreground="#0d01c2")
get_path_TButton.pack(side=BOTTOM, fill=X)
mainloop()
